package com.simplesoftwares.client.library.mywidgets;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Vector;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.simplesoftwares.client.library.appstructure.SuperModel;
import com.simplesoftwares.client.library.appstructure.search.Filter;
import com.simplesoftwares.client.library.appstructure.search.MyQuerry;
import com.simplesoftwares.client.library.libservice.OneToManyCompositeService;
import com.simplesoftwares.client.library.libservice.OneToManyCompositeServiceAsync;
import com.slicktechnologies.client.config.categoryconfig.CategoryTypes;
import com.slicktechnologies.client.utility.Screen;
import com.slicktechnologies.shared.common.helperlayer.ConfigCategory;
import com.slicktechnologies.shared.common.helperlayer.Type;

// TODO: Auto-generated Javadoc
/**
 * Can handel one to many relationships in such a way that change in one combobox fills many combobox with
 * corresponding data.
 *
 * @param <T> the generic type
 * @param <C> the generic type
 */
public class OneManyComboBox<T extends SuperModel,C extends SuperModel> implements ChangeHandler
{
	/** Combo Box where one relation is stored */
	private ObjectListBox<T> oneComboBox;
	
	/** Combo box where many relation is stored*/
	private ObjectListBox<C> manyComboBox;
	
	/** Querry object corresponding to one relation*/
	private MyQuerry oneQuerry;
	
	/** Querry object corresponding to many relation*/
	private MyQuerry manyQuerry;
	
	 /** Hash map storing one to many relation */
 	private  HashMap<T,List<C>>oneToManyHashMap;

	
	
	/**
	 * Instantiates a new one many combo box.
	 */
	public OneManyComboBox()
	{
		
	}

	/**
	 * Instantiates a new one many combo box.
	 *
	 * @param onecombo the onecombo
	 * @param manycombo the manycombo
	 */
	public OneManyComboBox(ObjectListBox<T> onecombo,ObjectListBox<C> manycombo)
	{
		this.oneComboBox=onecombo;
		this.manyComboBox=manycombo;
		oneComboBox.addChangeHandler(this);
	}
	
	/**
	 * Call to this method is necssery for one to many behaviour
	 */
	public void initializeHashMaps()
	{
		/** The service. */
		final OneToManyCompositeServiceAsync<T, C> service=GWT.create(OneToManyCompositeService.class);
		
		service.LoadOneToManyHashMap(oneQuerry, manyQuerry,new AsyncCallback<HashMap<T,List<C>>>() {

			@Override
			public void onFailure(Throwable caught) {
			
				
			}

			@Override
			public void onSuccess(HashMap<T, List<C>> result) {
				oneToManyHashMap=result;
				System.out.println("Size of HashMap "+oneToManyHashMap.size());
				setOneListBox();
				
			}
		});
    }
	
	 /**
 	 * Sets the one List box from database
 	 */
 	private void setOneListBox()
	    {
	    	Iterator<Entry<T, List<C>>>  it = oneToManyHashMap.entrySet().iterator();
	    	Vector<T>catvector=new Vector<T>();
	        while (it.hasNext()) {
	            Entry<T, List<C>> pairs = it.next();
	            catvector.add(pairs.getKey());
	            }
	        this.oneComboBox.setListItems(catvector);
	    }
	 
 	/**
 	 * Necessery to fill many combobox from one.
 	 */
 	protected void reactOnChange()
		{
			if(oneComboBox.getSelectedIndex()==0)
			{
				// Set many combobox to zeroth index.
				manyComboBox.setSelectedIndex(0);
				manyComboBox.removeAllItems();
				manyComboBox.addItem("--SELECT--");
				
				
			}
			
			else{
			
			T prodCat=oneComboBox.getSelectedItem();
		    List<C>vec=this.oneToManyHashMap.get(prodCat);
		    //if no corresponding many set it to zero
		    if(vec==null)
		    {
		    	manyComboBox.setSelectedIndex(0);
		    	manyComboBox.removeAllItems();
		    	manyComboBox.addItem("--SELECT--");
		    
		    }
		    else if(vec.size()==0)
		    {
		    	manyComboBox.setSelectedIndex(0);
		    	manyComboBox.removeAllItems();
		    	manyComboBox.addItem("--SELECT--");
		    	
		    }
		    else
		    {
		    Vector<C> vecprod=new Vector<C>();
		    vecprod.addAll(vec);
		    manyComboBox.setListItems(vecprod);
		    
		    }
			}
		}
		
		/* (non-Javadoc)
		 * @see com.google.gwt.event.dom.client.ChangeHandler#onChange(com.google.gwt.event.dom.client.ChangeEvent)
		 */
		
		@Override
		public void onChange(ChangeEvent event) 
		{
			
			reactOnChange();
		 }

		/**
		 * Gets the one combo box.
		 *
		 * @return the one combo box
		 */
		public ObjectListBox<T> getOneComboBox() {
			return oneComboBox;
		}

		/**
		 * Sets the one combo box.
		 *
		 * @param oneComboBox the new one combo box
		 */
		public void setOneComboBox(ObjectListBox<T> oneComboBox) {
			this.oneComboBox = oneComboBox;
		}

		/**
		 * Gets the many combo box.
		 *
		 * @return the many combo box
		 */
		public ObjectListBox<C> getManyComboBox() {
			return manyComboBox;
		}

		/**
		 * Sets the many combo box.
		 *
		 * @param manyComboBox the new many combo box
		 */
		public void setManyComboBox(ObjectListBox<C> manyComboBox) {
			this.manyComboBox = manyComboBox;
		}

		/**
		 * Gets the one querry.
		 *
		 * @return the one querry
		 */
		public MyQuerry getOneQuerry() {
			return oneQuerry;
		}

		/**
		 * Sets the one querry.
		 *
		 * @param oneQuerry the new one querry
		 */
		public void setOneQuerry(MyQuerry oneQuerry) {
			this.oneQuerry = oneQuerry;
		}

		/**
		 * Gets the many querry.
		 *
		 * @return the many querry
		 */
		public MyQuerry getManyQuerry() {
			return manyQuerry;
		}

		/**
		 * Sets the many querry.
		 *
		 * @param manyQuerry the new many querry
		 */
		public void setManyQuerry(MyQuerry manyQuerry) {
			this.manyQuerry = manyQuerry;
		}

		/**
		 * Gets the one to many hash map.
		 *
		 * @return the one to many hash map
		 */
		public HashMap<T, List<C>> getOneToManyHashMap() {
			return oneToManyHashMap;
		}

		/**
		 * Sets the one to many hash map.
		 *
		 * @param oneToManyHashMap the one to many hash map
		 */
		public void setOneToManyHashMap(HashMap<T, List<C>> oneToManyHashMap) {
			this.oneToManyHashMap = oneToManyHashMap;
		}
		
		
		
		
}
